Механизм обработки событий в Java весьма прост, достаточно мощный и очень гибкий. Не верите? Судите сами:
AnyComponent.addActionListener(ObWhoMustHandleEvents);Одному компоненту можно назначить, таким образом, несколько обработчиков событий. Каким же свойством должен объект, который сможет обработать событие (в нашем примере ObWhoMustHandleEvent)? Все очень просто - он должен имплементировать интерфейс ActionListener. В интерфейсе всего один метод: actionPerformed(ActionEvent e), который и нужно реализовать вашему объекту - обработчику события. Этот метод выполнится при возникновении события.
По аналогичной схеме обрабатываются и другие события. Например, чтоб обработать события от мыши, указываем функцией addMouseListener(ObWhoMustHandleEvents) объект, который будет их обрабатывать, этот объект должен имплементировать интерфейс MouseListener. Здесь нужно реализировать уже 5 функций mousePressed(MouseEvent e), mouseReleased(MouseEvent e), mouseEntered(MouseEvent e), mouseExited(MouseEvent e) и mouseClicked(MouseEvent e). И так далее. Вот функции которыми обладают все компоненты для регистрации обработчиков событий:
public class MainWindow extends JFrame implements WindowListener
{
//...........
//скажем объекту окна пусть сам свои событыя и обрабатывает
addWindowListener(this);
//реализируем методы интерфейса WindowListener
public void windowActivated(WindowEvent e)
{
doSomething();
}
public void windowClosing(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
//...........
}
Чтоб обработать событие активации в функции windowActivated(WindowEvent e) нам пришлось еще 6 пустых функций вписать ибо раз взялись имплементировать интерфейс то надо сделать это полностью, иначе класс свой абстрактным сделаем. Чтоб не вписывать пустые функции придуманы классы-адаптеры которые имплементируют соответствующие интерфейсы и содержат реализацию их методов по умолчанию. Например, для событий окна существует WindowAdapter, для событий мыши - MouseAdapter. Ваш класс обрабатывающий событие может унаследовать такой класс-адаптер и перегрузить нужный Вам метод для обработки конкретного события. Но как это использовать в примере выше? Ведь наш класс уже наследуется от JFrame а многократного наследования в Java нету! Выход простой - создадим специальный внутренний класс - обработчик событий окна (внутренний лучше потому что он будет иметь доступ к всем полям содержащего его класса). Пример:
public class MainWindow extends JFrame
{
//...........
//Действие 1
//скажем объекту окна что обрабатывать
//его события будет класс OurListener
//создавая его сходу
addWindowListener(new OurListener());
//Действие 2
//реализируем внутренний класс OurListener
class OurListener extends WindowAdapter
{
//перегружаем нужный нам метод
public void windowActivated(WindowEvent e)
{
doSomething();
}
}
//...........
}
А теперь оба окурка давим одновременно:) - перепишем этот код объединив действия 1 и 2 в одно:
public class MainWindow extends JFrame
{
//...........
//скажем объекту окна что обрабатывать
//его события будет класс Х!
//создадим его сходу с помощью
//конструктора родительского класса
//и тут же перегрузим нужный нам метод!
addWindowListener(new WindowAdapter()
{
public void windowActivated(WindowEvent e)
{
doSomething();
}
});
//...........
}
Ну как вам аргументец функции addWindowListener? Какое у этого класса название? Нету у него имени (да и незачем в принципе оно ему), он является потомком класса WindowAdapter один из методов которого мы перегрузили, большего нам от него и не надобно.
Осталось нам разобраться что за аргументы передаются в функции-обработчики событий. Как видим, они разные: в случае с событием типа action в функции actionPerformed аргументом есть объект типа ActionEvent, в функциях событий окна - аргументом есть WindowEvent, для обработчиков событий мыши аргументом будет MouseEvent. Как Вы уже догадались это все одного поля ягоды. Они все содержат информацию о соответствующем событии. Их предком является класс EventObject. С помощью метода getSource, которым обеспечивает данный класс своих потомков, Вы можете получить объект создавший событие. Кроме того у каждого из вышеперечисленных классов можно узнать специфические детали для каждого события, например у объекта MouseEvent можно узнать координаты мыши во время возникновения события, количество кликов, какой кнопкой кликали и т.д.
import java.awt.*;
import javax.swing.*;
//нижеследующее импортируем для работы с событиями
import java.awt.event.*;
public class EventApplet extends JApplet implements ActionListener
{
JButton button;
JTextArea ButtArea, MouseArea;
public void init()
{
Container contPane = getContentPane();
contPane.setLayout(new BoxLayout(contPane, BoxLayout.Y_AXIS));
button=new JButton("Our Button");
button.addActionListener(this);
ButtArea=new JTextArea(10,10);
//поместим наши JTextArea на панель которая
//может создать скроллинг
JScrollPane ScrollPane_butt = new JScrollPane(ButtArea);
//окружим эту панель рамкой с заголовком
ScrollPane_butt.setBorder(BorderFactory.createTitledBorder("Button actions:"));
//тут аналогично...
MouseArea=new JTextArea(10,10);
JScrollPane ScrollPane_mouse = new JScrollPane(MouseArea);
ScrollPane_mouse.setBorder(BorderFactory.createTitledBorder("Mouse actions:"));
//поместим нашу кнопку и JScrollPane панели
//которые содержат в себе наши JTextArea
//на главную панель апплета
contPane.add(button);
contPane.add(ScrollPane_butt);
contPane.add(ScrollPane_mouse);
//назначим територии апплета обработчик событий
//мыши создав его на ходу
addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e)
{
MouseArea.append("Mouse clicked"+e.getClickCount()+"times"+"\n");
}
public void mouseEntered(MouseEvent e)
{
MouseArea.append("Mouse entered"+"\n");
}
public void mouseExited(MouseEvent e)
{
MouseArea.append("Mouse exited"+"\n");
}
});
}
//обработаем нажатие кнопки
public void actionPerformed(ActionEvent e)
{
ButtArea.append("Button Clicked" + "\n");
}
}
Компилируем, смотрим. У кого не получилось - грузите проект, там кроме апплета есть еще аналогичное приложение (EventApp). Кстати, Вы заметили что при компиляции кроме файла главного класса еще какой-то файл EventApplet$1.class получается? Это не спам! Это наш анонимный внутренний класс-обработчик событий мыши. Ну теперь можно покликать по кнопке, повходить-выходить на территорию панели апплета не занятую нашими компонентами (возле кнопки ее больше всего должно быть) и покликать по этой территории. Попробуйте сделать многократный клик и посмотрите на запись событий в нижней текстовой области. При переполнении текстовых областей должна прокрутка появляться - не даром же мы их на специальные панели ставили!